﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace SRF.UI
{
    /// <summary>
    /// 数据源
    /// </summary>
    public class DataSource : IPager
    {
        Data.DBHelperBase dbhelper = Data.DBHelperFactory.GetDBHelper();
        string _selectSql, _countSql;
        Action<QueryParamterCollection> prepareParameter;
        DataTable dataTable;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="selectSql"></param>
        /// <param name="countSql"></param>
        public DataSource(string selectSql, string countSql = null, Action<QueryParamterCollection> prepareParameter = null)
        {
            this._selectSql = selectSql;
            this._countSql = countSql;

            this.prepareParameter = prepareParameter;
        }
        /// <summary>
        /// 数据行集合
        /// </summary>
        /// <returns></returns>
        public System.Data.DataRowCollection Rows
        {
            get
            {
                return Table.Rows;
            }
        }
        /// <summary>
        /// 数据表
        /// </summary>
        public System.Data.DataTable Table
        {
            get
            {
                LoadDataTable();

                return dataTable;
            }
        }

        private void LoadDataTable()
        {
            if (dataTable != null)
                return;

            if (string.IsNullOrEmpty(this._selectSql))
            {
                dataTable = new DataTable();
            }
            else
            {
                QueryParamterCollection parameters = GetParameters();
                if (prepareParameter != null)
                {
                    prepareParameter(parameters);
                }
                if (_perPageSize > 0)
                {
                    string page = System.Web.HttpContext.Current.Request["page"];

                    this._rowCount = dbhelper.GetQuery(this._countSql).SetParameter(parameters.ToDictionary()).UniqueResult<int>();
                    this._pageCount = this._rowCount / this._perPageSize + (this._rowCount % this._perPageSize > 0 ? 1 : 0);
                    this._curPageNo = string.IsNullOrEmpty(page) ? 1 : int.Parse(page);
                    this._curPageNo = this._curPageNo > this._pageCount ? this._pageCount : this._curPageNo;
                    this._curPageSize = this._curPageNo == this._pageCount ? this._rowCount % this._perPageSize : this._perPageSize;
                    int startRow = (this._curPageNo - 1) * this._perPageSize + 1;
                    //排序
                    string orderby = System.Web.HttpContext.Current.Request["order"];
                    if (!string.IsNullOrEmpty(orderby))
                    {
                        orderby = orderby.Substring(0, orderby.LastIndexOf('_')) + " " + orderby.Substring(orderby.LastIndexOf('_') + 1);
                    }
                    dataTable = dbhelper.GetQuery(this._selectSql).SetLimit(startRow, this._perPageSize).SetOrderBy(orderby).SetParameter(parameters.ToDictionary()).DataSet().Tables[0];
                }
                else
                {
                    dataTable = dbhelper.GetQuery(this._selectSql).SetParameter(parameters.ToDictionary()).DataSet().Tables[0];
                    this._rowCount = this._curPageSize = dataTable.Rows.Count;
                    this._pageCount = this._curPageNo = 1;
                }

            }
        }

        /// <summary>
        /// 获取页面上的参数
        /// </summary>
        /// <returns></returns>
        private QueryParamterCollection GetParameters()
        {
            QueryParamterCollection result = new QueryParamterCollection();
            System.Web.HttpRequest request = System.Web.HttpContext.Current.Request;

            for (int i = 0; i < request.Form.Count; i++)
            {
                result[request.Form.Keys[i]] = request.Form[i];
            }
            for (int i = 0; i < request.QueryString.Count; i++)
            {
                result[request.QueryString.Keys[i]] = request.QueryString[i];
            }

            return result;
        }

        #region 属性

        int _pageCount;
        int _perPageSize = 0;
        int _curPageSize;
        int _rowCount;
        int _curPageNo;

        public int PageCount { get { LoadDataTable(); return _pageCount; } }
        public int PerPageSize { get { LoadDataTable(); return _perPageSize; } set { _perPageSize = value; } }
        public int CurPageSize { get { LoadDataTable(); return _curPageSize; } }
        public int RowCount { get { LoadDataTable(); return _rowCount; } }
        /// <summary>
        /// 当前页 从1开始
        /// </summary>
        public int CurPageNo { get { LoadDataTable(); return _curPageNo; } }

        #endregion

        /// <summary>
        /// 空数据源
        /// </summary>
        public static DataSource Empty
        {
            get
            {
                return new DataSource("");
            }
        }
    }

    /// <summary>
    /// 参数集合（参数名和值的集合）
    /// </summary>
    public class QueryParamterCollection : System.Collections.Specialized.StringDictionary
    {
        /// <summary>
        /// 参数值加上通配符
        /// </summary>
        /// <param name="paraName">参数名</param>
        /// <param name="wildcard">通配符</param>
        public void Like(string paraName, string wildcard = "%")
        {
            if (ContainsKey(paraName))
            {
                this[paraName] = wildcard + this[paraName] + wildcard;
            }
        }
        /// <summary>
        /// 设置参数为开始时间
        /// </summary>
        /// <param name="paraName">参数名</param>
        public void StartDate(string paraName)
        {
            if (ContainsKey(paraName))
            {
                DateTime date;
                if (DateTime.TryParse(this[paraName], out date))
                {
                    this[paraName] = date.ToShortDateString();
                }
                else
                {
                    this[paraName] = "";
                }
            }
        }

        /// <summary>
        /// 设置参数为结束时间
        /// </summary>
        /// <param name="paraName">参数名</param>
        public void EndDate(string paraName)
        {
            if (ContainsKey(paraName))
            {
                DateTime date;
                if (DateTime.TryParse(this[paraName], out date))
                {
                    this[paraName] = (new DateTime(date.Year, date.Month, date.Day, 23, 59, 59)).ToString();
                }
                else
                {
                    this[paraName] = "";
                }
            }
        }
        public IDictionary<string, object> ToDictionary()
        {
            IDictionary<string, object> dict = new Dictionary<string, object>();
            foreach (string key in this.Keys)
            {
                dict.Add(key, this[key]);
            }

            return dict;
        }
    }

    /// <summary>
    /// DataScoure 扩展函数
    /// </summary>
    public static class DataSourceExtensions
    {
        /// <summary>
        /// 将DataSource对象装成json
        /// </summary>
        /// <param name="dataSource"></param>
        /// <returns></returns>
        public static string ToJson(this DataSource dataSource)
        {
            var json = new System.IO.StringWriter();
            Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
            Newtonsoft.Json.JsonWriter writer = new Newtonsoft.Json.JsonTextWriter(json);

            writer.WriteStartObject();
            writer.WritePropertyName("CurPageNo");
            serializer.Serialize(writer, dataSource.CurPageNo);
            writer.WritePropertyName("CurPageSize");
            serializer.Serialize(writer, dataSource.CurPageSize);
            writer.WritePropertyName("PageCount");
            serializer.Serialize(writer, dataSource.PageCount);
            writer.WritePropertyName("PerPageSize");
            serializer.Serialize(writer, dataSource.PerPageSize);
            writer.WritePropertyName("RowCount");
            serializer.Serialize(writer, dataSource.RowCount);
            writer.WritePropertyName("Rows");
            writer.WriteStartArray();
            foreach (DataRow row in dataSource.Rows)
            {
                writer.WriteStartObject();
                foreach (DataColumn column in row.Table.Columns)
                {
                    if (serializer.NullValueHandling == Newtonsoft.Json.NullValueHandling.Ignore && (row[column] == null || row[column] == DBNull.Value))
                        continue;

                    writer.WritePropertyName(column.ColumnName);
                    serializer.Serialize(writer, row[column]);
                }
                writer.WriteEndObject();
            }
            writer.WriteEndArray();
            writer.WriteEndObject();

            return json.ToString();
        }
    }
}